// Generated from code/ch25/Pie.g by ANTLR 4.9.0-SNAPSHOT


import { ATN } from "antlr4ts/atn/ATN";
import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer";
import { FailedPredicateException } from "antlr4ts/FailedPredicateException";
import { NotNull } from "antlr4ts/Decorators";
import { NoViableAltException } from "antlr4ts/NoViableAltException";
import { Override } from "antlr4ts/Decorators";
import { Parser } from "antlr4ts/Parser";
import { ParserRuleContext } from "antlr4ts/ParserRuleContext";
import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator";
import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener";
import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor";
import { RecognitionException } from "antlr4ts/RecognitionException";
import { RuleContext } from "antlr4ts/RuleContext";
//import { RuleVersion } from "antlr4ts/RuleVersion";
import { TerminalNode } from "antlr4ts/tree/TerminalNode";
import { Token } from "antlr4ts/Token";
import { TokenStream } from "antlr4ts/TokenStream";
import { Vocabulary } from "antlr4ts/Vocabulary";
import { VocabularyImpl } from "antlr4ts/VocabularyImpl";

import * as Utils from "antlr4ts/misc/Utils";

import { PieListener } from "./PieListener";
import { PieVisitor } from "./PieVisitor";


export class PieParser extends Parser {
	public static readonly T__0 = 1;
	public static readonly T__1 = 2;
	public static readonly T__2 = 3;
	public static readonly T__3 = 4;
	public static readonly T__4 = 5;
	public static readonly T__5 = 6;
	public static readonly T__6 = 7;
	public static readonly T__7 = 8;
	public static readonly T__8 = 9;
	public static readonly T__9 = 10;
	public static readonly T__10 = 11;
	public static readonly T__11 = 12;
	public static readonly T__12 = 13;
	public static readonly T__13 = 14;
	public static readonly T__14 = 15;
	public static readonly T__15 = 16;
	public static readonly T__16 = 17;
	public static readonly T__17 = 18;
	public static readonly T__18 = 19;
	public static readonly T__19 = 20;
	public static readonly T__20 = 21;
	public static readonly INT = 22;
	public static readonly FLOAT = 23;
	public static readonly CHAR = 24;
	public static readonly STRING = 25;
	public static readonly ID = 26;
	public static readonly NL = 27;
	public static readonly WS = 28;
	public static readonly SL_COMMENT = 29;
	public static readonly RULE_program = 0;
	public static readonly RULE_atom = 1;
	public static readonly RULE_mulexpr = 2;
	public static readonly RULE_addexpr = 3;
	public static readonly RULE_expr = 4;
	public static readonly RULE_statement = 5;
	public static readonly RULE_slist = 6;
	public static readonly RULE_structDefinition = 7;
	public static readonly RULE_vardef = 8;
	public static readonly RULE_instance = 9;
	public static readonly RULE_qid = 10;
	public static readonly RULE_functionDefinition = 11;
	public static readonly RULE_call = 12;
	// tslint:disable:no-trailing-whitespace
	public static readonly ruleNames: string[] = [
		"program", "atom", "mulexpr", "addexpr", "expr", "statement", "slist", 
		"structDefinition", "vardef", "instance", "qid", "functionDefinition", 
		"call",
	];

	private static readonly _LITERAL_NAMES: Array<string | undefined> = [
		undefined, "'('", "')'", "'*'", "'+'", "'-'", "'=='", "'<'", "'='", "'return'", 
		"'print'", "'if'", "'else'", "'while'", "':'", "'.'", "'struct'", "'{'", 
		"','", "'}'", "'new'", "'def'",
	];
	private static readonly _SYMBOLIC_NAMES: Array<string | undefined> = [
		undefined, undefined, undefined, undefined, undefined, undefined, undefined, 
		undefined, undefined, undefined, undefined, undefined, undefined, undefined, 
		undefined, undefined, undefined, undefined, undefined, undefined, undefined, 
		undefined, "INT", "FLOAT", "CHAR", "STRING", "ID", "NL", "WS", "SL_COMMENT",
	];
	public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(PieParser._LITERAL_NAMES, PieParser._SYMBOLIC_NAMES, []);

	// @Override
	// @NotNull
	public get vocabulary(): Vocabulary {
		return PieParser.VOCABULARY;
	}
	// tslint:enable:no-trailing-whitespace

	// @Override
	public get grammarFileName(): string { return "Pie.g"; }

	// @Override
	public get ruleNames(): string[] { return PieParser.ruleNames; }

	// @Override
	public get serializedATN(): string { return PieParser._serializedATN; }

	protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException {
		return new FailedPredicateException(this, predicate, message);
	}

	constructor(input: TokenStream) {
		super(input);
		this._interp = new ParserATNSimulator(PieParser._ATN, this);
	}
	// @RuleVersion(0)
	public program(): ProgramContext {
		let _localctx: ProgramContext = new ProgramContext(this._ctx, this.state);
		this.enterRule(_localctx, 0, PieParser.RULE_program);
		let _la: number;
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 28;
			this._errHandler.sync(this);
			_la = this._input.LA(1);
			do {
				{
				this.state = 28;
				this._errHandler.sync(this);
				switch (this._input.LA(1)) {
				case PieParser.T__20:
					{
					this.state = 26;
					this.functionDefinition();
					}
					break;
				case PieParser.T__8:
				case PieParser.T__9:
				case PieParser.T__10:
				case PieParser.T__12:
				case PieParser.T__15:
				case PieParser.ID:
				case PieParser.NL:
					{
					this.state = 27;
					this.statement();
					}
					break;
				default:
					throw new NoViableAltException(this);
				}
				}
				this.state = 30;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
			} while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << PieParser.T__8) | (1 << PieParser.T__9) | (1 << PieParser.T__10) | (1 << PieParser.T__12) | (1 << PieParser.T__15) | (1 << PieParser.T__20) | (1 << PieParser.ID) | (1 << PieParser.NL))) !== 0));
			this.state = 32;
			this.match(PieParser.EOF);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public atom(): AtomContext {
		let _localctx: AtomContext = new AtomContext(this._ctx, this.state);
		this.enterRule(_localctx, 2, PieParser.RULE_atom);
		try {
			this.state = 45;
			this._errHandler.sync(this);
			switch ( this.interpreter.adaptivePredict(this._input, 2, this._ctx) ) {
			case 1:
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 34;
				this.match(PieParser.INT);
				}
				break;

			case 2:
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 35;
				this.match(PieParser.CHAR);
				}
				break;

			case 3:
				this.enterOuterAlt(_localctx, 3);
				{
				this.state = 36;
				this.match(PieParser.FLOAT);
				}
				break;

			case 4:
				this.enterOuterAlt(_localctx, 4);
				{
				this.state = 37;
				this.match(PieParser.STRING);
				}
				break;

			case 5:
				this.enterOuterAlt(_localctx, 5);
				{
				this.state = 38;
				this.qid();
				}
				break;

			case 6:
				this.enterOuterAlt(_localctx, 6);
				{
				this.state = 39;
				this.call();
				}
				break;

			case 7:
				this.enterOuterAlt(_localctx, 7);
				{
				this.state = 40;
				this.instance();
				}
				break;

			case 8:
				this.enterOuterAlt(_localctx, 8);
				{
				this.state = 41;
				this.match(PieParser.T__0);
				this.state = 42;
				this.expr();
				this.state = 43;
				this.match(PieParser.T__1);
				}
				break;
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public mulexpr(): MulexprContext {
		let _localctx: MulexprContext = new MulexprContext(this._ctx, this.state);
		this.enterRule(_localctx, 4, PieParser.RULE_mulexpr);
		let _la: number;
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 47;
			this.atom();
			this.state = 52;
			this._errHandler.sync(this);
			_la = this._input.LA(1);
			while (_la === PieParser.T__2) {
				{
				{
				this.state = 48;
				this.match(PieParser.T__2);
				this.state = 49;
				this.atom();
				}
				}
				this.state = 54;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
			}
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public addexpr(): AddexprContext {
		let _localctx: AddexprContext = new AddexprContext(this._ctx, this.state);
		this.enterRule(_localctx, 6, PieParser.RULE_addexpr);
		let _la: number;
		try {
			this.state = 71;
			this._errHandler.sync(this);
			switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) {
			case 1:
				_localctx = new AddExprContext(_localctx);
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 55;
				this.mulexpr();
				this.state = 60;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				while (_la === PieParser.T__3) {
					{
					{
					this.state = 56;
					this.match(PieParser.T__3);
					this.state = 57;
					this.mulexpr();
					}
					}
					this.state = 62;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				}
				}
				break;

			case 2:
				_localctx = new SubExprContext(_localctx);
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 63;
				this.mulexpr();
				this.state = 68;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				while (_la === PieParser.T__4) {
					{
					{
					this.state = 64;
					this.match(PieParser.T__4);
					this.state = 65;
					this.mulexpr();
					}
					}
					this.state = 70;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				}
				}
				break;
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public expr(): ExprContext {
		let _localctx: ExprContext = new ExprContext(this._ctx, this.state);
		this.enterRule(_localctx, 8, PieParser.RULE_expr);
		let _la: number;
		try {
			this.state = 83;
			this._errHandler.sync(this);
			switch ( this.interpreter.adaptivePredict(this._input, 9, this._ctx) ) {
			case 1:
				_localctx = new EqExprContext(_localctx);
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 73;
				this.addexpr();
				this.state = 76;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				if (_la === PieParser.T__5) {
					{
					this.state = 74;
					this.match(PieParser.T__5);
					this.state = 75;
					this.addexpr();
					}
				}

				}
				break;

			case 2:
				_localctx = new LtExprContext(_localctx);
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 78;
				this.addexpr();
				this.state = 81;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				if (_la === PieParser.T__6) {
					{
					this.state = 79;
					this.match(PieParser.T__6);
					this.state = 80;
					this.addexpr();
					}
				}

				}
				break;
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public statement(): StatementContext {
		let _localctx: StatementContext = new StatementContext(this._ctx, this.state);
		this.enterRule(_localctx, 10, PieParser.RULE_statement);
		try {
			this.state = 114;
			this._errHandler.sync(this);
			switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) {
			case 1:
				_localctx = new StructDefStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 85;
				this.structDefinition();
				}
				break;

			case 2:
				_localctx = new AssignStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 86;
				this.qid();
				this.state = 87;
				this.match(PieParser.T__7);
				this.state = 88;
				this.expr();
				this.state = 89;
				this.match(PieParser.NL);
				}
				break;

			case 3:
				_localctx = new ReturnStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 3);
				{
				this.state = 91;
				this.match(PieParser.T__8);
				this.state = 92;
				this.expr();
				this.state = 93;
				this.match(PieParser.NL);
				}
				break;

			case 4:
				_localctx = new PrintStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 4);
				{
				this.state = 95;
				this.match(PieParser.T__9);
				this.state = 96;
				this.expr();
				this.state = 97;
				this.match(PieParser.NL);
				}
				break;

			case 5:
				_localctx = new IfStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 5);
				{
				this.state = 99;
				this.match(PieParser.T__10);
				this.state = 100;
				this.expr();
				this.state = 101;
				this.slist();
				this.state = 104;
				this._errHandler.sync(this);
				switch ( this.interpreter.adaptivePredict(this._input, 10, this._ctx) ) {
				case 1:
					{
					this.state = 102;
					this.match(PieParser.T__11);
					this.state = 103;
					this.slist();
					}
					break;
				}
				}
				break;

			case 6:
				_localctx = new WhileStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 6);
				{
				this.state = 106;
				this.match(PieParser.T__12);
				this.state = 107;
				this.expr();
				this.state = 108;
				this.slist();
				}
				break;

			case 7:
				_localctx = new CallStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 7);
				{
				this.state = 110;
				this.call();
				this.state = 111;
				this.match(PieParser.NL);
				}
				break;

			case 8:
				_localctx = new EmptyStatementContext(_localctx);
				this.enterOuterAlt(_localctx, 8);
				{
				this.state = 113;
				this.match(PieParser.NL);
				}
				break;
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public slist(): SlistContext {
		let _localctx: SlistContext = new SlistContext(this._ctx, this.state);
		this.enterRule(_localctx, 12, PieParser.RULE_slist);
		let _la: number;
		try {
			this.state = 127;
			this._errHandler.sync(this);
			switch (this._input.LA(1)) {
			case PieParser.T__13:
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 116;
				this.match(PieParser.T__13);
				this.state = 117;
				this.match(PieParser.NL);
				this.state = 119;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				do {
					{
					{
					this.state = 118;
					this.statement();
					}
					}
					this.state = 121;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				} while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << PieParser.T__8) | (1 << PieParser.T__9) | (1 << PieParser.T__10) | (1 << PieParser.T__12) | (1 << PieParser.T__15) | (1 << PieParser.ID) | (1 << PieParser.NL))) !== 0));
				this.state = 123;
				this.match(PieParser.T__14);
				this.state = 124;
				this.match(PieParser.NL);
				}
				break;
			case PieParser.T__8:
			case PieParser.T__9:
			case PieParser.T__10:
			case PieParser.T__12:
			case PieParser.T__15:
			case PieParser.ID:
			case PieParser.NL:
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 126;
				this.statement();
				}
				break;
			default:
				throw new NoViableAltException(this);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public structDefinition(): StructDefinitionContext {
		let _localctx: StructDefinitionContext = new StructDefinitionContext(this._ctx, this.state);
		this.enterRule(_localctx, 14, PieParser.RULE_structDefinition);
		let _la: number;
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 129;
			this.match(PieParser.T__15);
			this.state = 130;
			this.match(PieParser.ID);
			this.state = 131;
			this.match(PieParser.T__16);
			this.state = 132;
			this.vardef();
			this.state = 137;
			this._errHandler.sync(this);
			_la = this._input.LA(1);
			while (_la === PieParser.T__17) {
				{
				{
				this.state = 133;
				this.match(PieParser.T__17);
				this.state = 134;
				this.vardef();
				}
				}
				this.state = 139;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
			}
			this.state = 140;
			this.match(PieParser.T__18);
			this.state = 141;
			this.match(PieParser.NL);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public vardef(): VardefContext {
		let _localctx: VardefContext = new VardefContext(this._ctx, this.state);
		this.enterRule(_localctx, 16, PieParser.RULE_vardef);
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 143;
			this.match(PieParser.ID);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public instance(): InstanceContext {
		let _localctx: InstanceContext = new InstanceContext(this._ctx, this.state);
		this.enterRule(_localctx, 18, PieParser.RULE_instance);
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 145;
			this.match(PieParser.T__19);
			this.state = 146;
			this.match(PieParser.ID);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public qid(): QidContext {
		let _localctx: QidContext = new QidContext(this._ctx, this.state);
		this.enterRule(_localctx, 20, PieParser.RULE_qid);
		let _la: number;
		try {
			this.state = 156;
			this._errHandler.sync(this);
			switch ( this.interpreter.adaptivePredict(this._input, 16, this._ctx) ) {
			case 1:
				_localctx = new SimpleVarContext(_localctx);
				this.enterOuterAlt(_localctx, 1);
				{
				this.state = 148;
				this.match(PieParser.ID);
				}
				break;

			case 2:
				_localctx = new FieldVarContext(_localctx);
				this.enterOuterAlt(_localctx, 2);
				{
				this.state = 149;
				this.match(PieParser.ID);
				this.state = 152;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				do {
					{
					{
					this.state = 150;
					this.match(PieParser.T__14);
					this.state = 151;
					this.match(PieParser.ID);
					}
					}
					this.state = 154;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				} while (_la === PieParser.T__14);
				}
				break;
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public functionDefinition(): FunctionDefinitionContext {
		let _localctx: FunctionDefinitionContext = new FunctionDefinitionContext(this._ctx, this.state);
		this.enterRule(_localctx, 22, PieParser.RULE_functionDefinition);
		let _la: number;
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 158;
			this.match(PieParser.T__20);
			this.state = 159;
			this.match(PieParser.ID);
			this.state = 160;
			this.match(PieParser.T__0);
			this.state = 169;
			this._errHandler.sync(this);
			_la = this._input.LA(1);
			if (_la === PieParser.ID) {
				{
				this.state = 161;
				this.vardef();
				this.state = 166;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				while (_la === PieParser.T__17) {
					{
					{
					this.state = 162;
					this.match(PieParser.T__17);
					this.state = 163;
					this.vardef();
					}
					}
					this.state = 168;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				}
				}
			}

			this.state = 171;
			this.match(PieParser.T__1);
			this.state = 172;
			this.slist();
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}
	// @RuleVersion(0)
	public call(): CallContext {
		let _localctx: CallContext = new CallContext(this._ctx, this.state);
		this.enterRule(_localctx, 24, PieParser.RULE_call);
		let _la: number;
		try {
			this.enterOuterAlt(_localctx, 1);
			{
			this.state = 174;
			this.match(PieParser.ID);
			this.state = 175;
			this.match(PieParser.T__0);
			this.state = 184;
			this._errHandler.sync(this);
			_la = this._input.LA(1);
			if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << PieParser.T__0) | (1 << PieParser.T__19) | (1 << PieParser.INT) | (1 << PieParser.FLOAT) | (1 << PieParser.CHAR) | (1 << PieParser.STRING) | (1 << PieParser.ID))) !== 0)) {
				{
				this.state = 176;
				this.expr();
				this.state = 181;
				this._errHandler.sync(this);
				_la = this._input.LA(1);
				while (_la === PieParser.T__17) {
					{
					{
					this.state = 177;
					this.match(PieParser.T__17);
					this.state = 178;
					this.expr();
					}
					}
					this.state = 183;
					this._errHandler.sync(this);
					_la = this._input.LA(1);
				}
				}
			}

			this.state = 186;
			this.match(PieParser.T__1);
			}
		}
		catch (re) {
			if (re instanceof RecognitionException) {
				_localctx.exception = re;
				this._errHandler.reportError(this, re);
				this._errHandler.recover(this, re);
			} else {
				throw re;
			}
		}
		finally {
			this.exitRule();
		}
		return _localctx;
	}

	public static readonly _serializedATN: string =
		"\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03\x1F\xBF\x04\x02" +
		"\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" +
		"\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" +
		"\x0E\t\x0E\x03\x02\x03\x02\x06\x02\x1F\n\x02\r\x02\x0E\x02 \x03\x02\x03" +
		"\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" +
		"\x03\x03\x03\x03\x03\x05\x030\n\x03\x03\x04\x03\x04\x03\x04\x07\x045\n" +
		"\x04\f\x04\x0E\x048\v\x04\x03\x05\x03\x05\x03\x05\x07\x05=\n\x05\f\x05" +
		"\x0E\x05@\v\x05\x03\x05\x03\x05\x03\x05\x07\x05E\n\x05\f\x05\x0E\x05H" +
		"\v\x05\x05\x05J\n\x05\x03\x06\x03\x06\x03\x06\x05\x06O\n\x06\x03\x06\x03" +
		"\x06\x03\x06\x05\x06T\n\x06\x05\x06V\n\x06\x03\x07\x03\x07\x03\x07\x03" +
		"\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03" +
		"\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05\x07k\n\x07\x03" +
		"\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05\x07u" +
		"\n\x07\x03\b\x03\b\x03\b\x06\bz\n\b\r\b\x0E\b{\x03\b\x03\b\x03\b\x03\b" +
		"\x05\b\x82\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x07\t\x8A\n\t\f\t\x0E" +
		"\t\x8D\v\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\v\x03\v\x03\v\x03\f\x03\f" +
		"\x03\f\x03\f\x06\f\x9B\n\f\r\f\x0E\f\x9C\x05\f\x9F\n\f\x03\r\x03\r\x03" +
		"\r\x03\r\x03\r\x03\r\x07\r\xA7\n\r\f\r\x0E\r\xAA\v\r\x05\r\xAC\n\r\x03" +
		"\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x07\x0E\xB6\n\x0E" +
		"\f\x0E\x0E\x0E\xB9\v\x0E\x05\x0E\xBB\n\x0E\x03\x0E\x03\x0E\x03\x0E\x02" +
		"\x02\x02\x0F\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02" +
		"\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x02\x02\x02\xD2\x02\x1E\x03\x02" +
		"\x02\x02\x04/\x03\x02\x02\x02\x061\x03\x02\x02\x02\bI\x03\x02\x02\x02" +
		"\nU\x03\x02\x02\x02\ft\x03\x02\x02\x02\x0E\x81\x03\x02\x02\x02\x10\x83" +
		"\x03\x02\x02\x02\x12\x91\x03\x02\x02\x02\x14\x93\x03\x02\x02\x02\x16\x9E" +
		"\x03\x02\x02\x02\x18\xA0\x03\x02\x02\x02\x1A\xB0\x03\x02\x02\x02\x1C\x1F" +
		"\x05\x18\r\x02\x1D\x1F\x05\f\x07\x02\x1E\x1C\x03\x02\x02\x02\x1E\x1D\x03" +
		"\x02\x02\x02\x1F \x03\x02\x02\x02 \x1E\x03\x02\x02\x02 !\x03\x02\x02\x02" +
		"!\"\x03\x02\x02\x02\"#\x07\x02\x02\x03#\x03\x03\x02\x02\x02$0\x07\x18" +
		"\x02\x02%0\x07\x1A\x02\x02&0\x07\x19\x02\x02\'0\x07\x1B\x02\x02(0\x05" +
		"\x16\f\x02)0\x05\x1A\x0E\x02*0\x05\x14\v\x02+,\x07\x03\x02\x02,-\x05\n" +
		"\x06\x02-.\x07\x04\x02\x02.0\x03\x02\x02\x02/$\x03\x02\x02\x02/%\x03\x02" +
		"\x02\x02/&\x03\x02\x02\x02/\'\x03\x02\x02\x02/(\x03\x02\x02\x02/)\x03" +
		"\x02\x02\x02/*\x03\x02\x02\x02/+\x03\x02\x02\x020\x05\x03\x02\x02\x02" +
		"16\x05\x04\x03\x0223\x07\x05\x02\x0235\x05\x04\x03\x0242\x03\x02\x02\x02" +
		"58\x03\x02\x02\x0264\x03\x02\x02\x0267\x03\x02\x02\x027\x07\x03\x02\x02" +
		"\x0286\x03\x02\x02\x029>\x05\x06\x04\x02:;\x07\x06\x02\x02;=\x05\x06\x04" +
		"\x02<:\x03\x02\x02\x02=@\x03\x02\x02\x02><\x03\x02\x02\x02>?\x03\x02\x02" +
		"\x02?J\x03\x02\x02\x02@>\x03\x02\x02\x02AF\x05\x06\x04\x02BC\x07\x07\x02" +
		"\x02CE\x05\x06\x04\x02DB\x03\x02\x02\x02EH\x03\x02\x02\x02FD\x03\x02\x02" +
		"\x02FG\x03\x02\x02\x02GJ\x03\x02\x02\x02HF\x03\x02\x02\x02I9\x03\x02\x02" +
		"\x02IA\x03\x02\x02\x02J\t\x03\x02\x02\x02KN\x05\b\x05\x02LM\x07\b\x02" +
		"\x02MO\x05\b\x05\x02NL\x03\x02\x02\x02NO\x03\x02\x02\x02OV\x03\x02\x02" +
		"\x02PS\x05\b\x05\x02QR\x07\t\x02\x02RT\x05\b\x05\x02SQ\x03\x02\x02\x02" +
		"ST\x03\x02\x02\x02TV\x03\x02\x02\x02UK\x03\x02\x02\x02UP\x03\x02\x02\x02" +
		"V\v\x03\x02\x02\x02Wu\x05\x10\t\x02XY\x05\x16\f\x02YZ\x07\n\x02\x02Z[" +
		"\x05\n\x06\x02[\\\x07\x1D\x02\x02\\u\x03\x02\x02\x02]^\x07\v\x02\x02^" +
		"_\x05\n\x06\x02_`\x07\x1D\x02\x02`u\x03\x02\x02\x02ab\x07\f\x02\x02bc" +
		"\x05\n\x06\x02cd\x07\x1D\x02\x02du\x03\x02\x02\x02ef\x07\r\x02\x02fg\x05" +
		"\n\x06\x02gj\x05\x0E\b\x02hi\x07\x0E\x02\x02ik\x05\x0E\b\x02jh\x03\x02" +
		"\x02\x02jk\x03\x02\x02\x02ku\x03\x02\x02\x02lm\x07\x0F\x02\x02mn\x05\n" +
		"\x06\x02no\x05\x0E\b\x02ou\x03\x02\x02\x02pq\x05\x1A\x0E\x02qr\x07\x1D" +
		"\x02\x02ru\x03\x02\x02\x02su\x07\x1D\x02\x02tW\x03\x02\x02\x02tX\x03\x02" +
		"\x02\x02t]\x03\x02\x02\x02ta\x03\x02\x02\x02te\x03\x02\x02\x02tl\x03\x02" +
		"\x02\x02tp\x03\x02\x02\x02ts\x03\x02\x02\x02u\r\x03\x02\x02\x02vw\x07" +
		"\x10\x02\x02wy\x07\x1D\x02\x02xz\x05\f\x07\x02yx\x03\x02\x02\x02z{\x03" +
		"\x02\x02\x02{y\x03\x02\x02\x02{|\x03\x02\x02\x02|}\x03\x02\x02\x02}~\x07" +
		"\x11\x02\x02~\x7F\x07\x1D\x02\x02\x7F\x82\x03\x02\x02\x02\x80\x82\x05" +
		"\f\x07\x02\x81v\x03\x02\x02\x02\x81\x80\x03\x02\x02\x02\x82\x0F\x03\x02" +
		"\x02\x02\x83\x84\x07\x12\x02\x02\x84\x85\x07\x1C\x02\x02\x85\x86\x07\x13" +
		"\x02\x02\x86\x8B\x05\x12\n\x02\x87\x88\x07\x14\x02\x02\x88\x8A\x05\x12" +
		"\n\x02\x89\x87\x03\x02\x02\x02\x8A\x8D\x03\x02\x02\x02\x8B\x89\x03\x02" +
		"\x02\x02\x8B\x8C\x03\x02\x02\x02\x8C\x8E\x03\x02\x02\x02\x8D\x8B\x03\x02" +
		"\x02\x02\x8E\x8F\x07\x15\x02\x02\x8F\x90\x07\x1D\x02\x02\x90\x11\x03\x02" +
		"\x02\x02\x91\x92\x07\x1C\x02\x02\x92\x13\x03\x02\x02\x02\x93\x94\x07\x16" +
		"\x02\x02\x94\x95\x07\x1C\x02\x02\x95\x15\x03\x02\x02\x02\x96\x9F\x07\x1C" +
		"\x02\x02\x97\x9A\x07\x1C\x02\x02\x98\x99\x07\x11\x02\x02\x99\x9B\x07\x1C" +
		"\x02\x02\x9A\x98\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02\x9C\x9A\x03\x02" +
		"\x02\x02\x9C\x9D\x03\x02\x02\x02\x9D\x9F\x03\x02\x02\x02\x9E\x96\x03\x02" +
		"\x02\x02\x9E\x97\x03\x02\x02\x02\x9F\x17\x03\x02\x02\x02\xA0\xA1\x07\x17" +
		"\x02\x02\xA1\xA2\x07\x1C\x02\x02\xA2\xAB\x07\x03\x02\x02\xA3\xA8\x05\x12" +
		"\n\x02\xA4\xA5\x07\x14\x02\x02\xA5\xA7\x05\x12\n\x02\xA6\xA4\x03\x02\x02" +
		"\x02\xA7\xAA\x03\x02\x02\x02\xA8\xA6\x03\x02\x02\x02\xA8\xA9\x03\x02\x02" +
		"\x02\xA9\xAC\x03\x02\x02\x02\xAA\xA8\x03\x02\x02\x02\xAB\xA3\x03\x02\x02" +
		"\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAD\x03\x02\x02\x02\xAD\xAE\x07\x04\x02" +
		"\x02\xAE\xAF\x05\x0E\b\x02\xAF\x19\x03\x02\x02\x02\xB0\xB1\x07\x1C\x02" +
		"\x02\xB1\xBA\x07\x03\x02\x02\xB2\xB7\x05\n\x06\x02\xB3\xB4\x07\x14\x02" +
		"\x02\xB4\xB6\x05\n\x06\x02\xB5\xB3\x03\x02\x02\x02\xB6\xB9\x03\x02\x02" +
		"\x02\xB7\xB5\x03\x02\x02\x02\xB7\xB8\x03\x02\x02\x02\xB8\xBB\x03\x02\x02" +
		"\x02\xB9\xB7\x03\x02\x02\x02\xBA\xB2\x03\x02\x02\x02\xBA\xBB\x03\x02\x02" +
		"\x02\xBB\xBC\x03\x02\x02\x02\xBC\xBD\x07\x04\x02\x02\xBD\x1B\x03\x02\x02" +
		"\x02\x17\x1E /6>FINSUjt{\x81\x8B\x9C\x9E\xA8\xAB\xB7\xBA";
	public static __ATN: ATN;
	public static get _ATN(): ATN {
		if (!PieParser.__ATN) {
			PieParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(PieParser._serializedATN));
		}

		return PieParser.__ATN;
	}

}

export class ProgramContext extends ParserRuleContext {
	public EOF(): TerminalNode { return this.getToken(PieParser.EOF, 0); }
	public functionDefinition(): FunctionDefinitionContext[];
	public functionDefinition(i: number): FunctionDefinitionContext;
	public functionDefinition(i?: number): FunctionDefinitionContext | FunctionDefinitionContext[] {
		if (i === undefined) {
			return this.getRuleContexts(FunctionDefinitionContext);
		} else {
			return this.getRuleContext(i, FunctionDefinitionContext);
		}
	}
	public statement(): StatementContext[];
	public statement(i: number): StatementContext;
	public statement(i?: number): StatementContext | StatementContext[] {
		if (i === undefined) {
			return this.getRuleContexts(StatementContext);
		} else {
			return this.getRuleContext(i, StatementContext);
		}
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_program; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterProgram) {
			listener.enterProgram(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitProgram) {
			listener.exitProgram(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitProgram) {
			return visitor.visitProgram(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class AtomContext extends ParserRuleContext {
	public INT(): TerminalNode | undefined { return this.tryGetToken(PieParser.INT, 0); }
	public CHAR(): TerminalNode | undefined { return this.tryGetToken(PieParser.CHAR, 0); }
	public FLOAT(): TerminalNode | undefined { return this.tryGetToken(PieParser.FLOAT, 0); }
	public STRING(): TerminalNode | undefined { return this.tryGetToken(PieParser.STRING, 0); }
	public qid(): QidContext | undefined {
		return this.tryGetRuleContext(0, QidContext);
	}
	public call(): CallContext | undefined {
		return this.tryGetRuleContext(0, CallContext);
	}
	public instance(): InstanceContext | undefined {
		return this.tryGetRuleContext(0, InstanceContext);
	}
	public expr(): ExprContext | undefined {
		return this.tryGetRuleContext(0, ExprContext);
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_atom; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterAtom) {
			listener.enterAtom(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitAtom) {
			listener.exitAtom(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitAtom) {
			return visitor.visitAtom(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class MulexprContext extends ParserRuleContext {
	public atom(): AtomContext[];
	public atom(i: number): AtomContext;
	public atom(i?: number): AtomContext | AtomContext[] {
		if (i === undefined) {
			return this.getRuleContexts(AtomContext);
		} else {
			return this.getRuleContext(i, AtomContext);
		}
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_mulexpr; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterMulexpr) {
			listener.enterMulexpr(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitMulexpr) {
			listener.exitMulexpr(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitMulexpr) {
			return visitor.visitMulexpr(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class AddexprContext extends ParserRuleContext {
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_addexpr; }
	public copyFrom(ctx: AddexprContext): void {
		super.copyFrom(ctx);
	}
}
export class AddExprContext extends AddexprContext {
	public mulexpr(): MulexprContext[];
	public mulexpr(i: number): MulexprContext;
	public mulexpr(i?: number): MulexprContext | MulexprContext[] {
		if (i === undefined) {
			return this.getRuleContexts(MulexprContext);
		} else {
			return this.getRuleContext(i, MulexprContext);
		}
	}
	constructor(ctx: AddexprContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterAddExpr) {
			listener.enterAddExpr(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitAddExpr) {
			listener.exitAddExpr(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitAddExpr) {
			return visitor.visitAddExpr(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class SubExprContext extends AddexprContext {
	public mulexpr(): MulexprContext[];
	public mulexpr(i: number): MulexprContext;
	public mulexpr(i?: number): MulexprContext | MulexprContext[] {
		if (i === undefined) {
			return this.getRuleContexts(MulexprContext);
		} else {
			return this.getRuleContext(i, MulexprContext);
		}
	}
	constructor(ctx: AddexprContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterSubExpr) {
			listener.enterSubExpr(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitSubExpr) {
			listener.exitSubExpr(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitSubExpr) {
			return visitor.visitSubExpr(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class ExprContext extends ParserRuleContext {
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_expr; }
	public copyFrom(ctx: ExprContext): void {
		super.copyFrom(ctx);
	}
}
export class EqExprContext extends ExprContext {
	public addexpr(): AddexprContext[];
	public addexpr(i: number): AddexprContext;
	public addexpr(i?: number): AddexprContext | AddexprContext[] {
		if (i === undefined) {
			return this.getRuleContexts(AddexprContext);
		} else {
			return this.getRuleContext(i, AddexprContext);
		}
	}
	constructor(ctx: ExprContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterEqExpr) {
			listener.enterEqExpr(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitEqExpr) {
			listener.exitEqExpr(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitEqExpr) {
			return visitor.visitEqExpr(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class LtExprContext extends ExprContext {
	public addexpr(): AddexprContext[];
	public addexpr(i: number): AddexprContext;
	public addexpr(i?: number): AddexprContext | AddexprContext[] {
		if (i === undefined) {
			return this.getRuleContexts(AddexprContext);
		} else {
			return this.getRuleContext(i, AddexprContext);
		}
	}
	constructor(ctx: ExprContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterLtExpr) {
			listener.enterLtExpr(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitLtExpr) {
			listener.exitLtExpr(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitLtExpr) {
			return visitor.visitLtExpr(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class StatementContext extends ParserRuleContext {
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_statement; }
	public copyFrom(ctx: StatementContext): void {
		super.copyFrom(ctx);
	}
}
export class StructDefStatementContext extends StatementContext {
	public structDefinition(): StructDefinitionContext {
		return this.getRuleContext(0, StructDefinitionContext);
	}
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterStructDefStatement) {
			listener.enterStructDefStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitStructDefStatement) {
			listener.exitStructDefStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitStructDefStatement) {
			return visitor.visitStructDefStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class AssignStatementContext extends StatementContext {
	public qid(): QidContext {
		return this.getRuleContext(0, QidContext);
	}
	public expr(): ExprContext {
		return this.getRuleContext(0, ExprContext);
	}
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterAssignStatement) {
			listener.enterAssignStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitAssignStatement) {
			listener.exitAssignStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitAssignStatement) {
			return visitor.visitAssignStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class ReturnStatementContext extends StatementContext {
	public expr(): ExprContext {
		return this.getRuleContext(0, ExprContext);
	}
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterReturnStatement) {
			listener.enterReturnStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitReturnStatement) {
			listener.exitReturnStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitReturnStatement) {
			return visitor.visitReturnStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class PrintStatementContext extends StatementContext {
	public expr(): ExprContext {
		return this.getRuleContext(0, ExprContext);
	}
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterPrintStatement) {
			listener.enterPrintStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitPrintStatement) {
			listener.exitPrintStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitPrintStatement) {
			return visitor.visitPrintStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class IfStatementContext extends StatementContext {
	public expr(): ExprContext {
		return this.getRuleContext(0, ExprContext);
	}
	public slist(): SlistContext[];
	public slist(i: number): SlistContext;
	public slist(i?: number): SlistContext | SlistContext[] {
		if (i === undefined) {
			return this.getRuleContexts(SlistContext);
		} else {
			return this.getRuleContext(i, SlistContext);
		}
	}
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterIfStatement) {
			listener.enterIfStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitIfStatement) {
			listener.exitIfStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitIfStatement) {
			return visitor.visitIfStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class WhileStatementContext extends StatementContext {
	public expr(): ExprContext {
		return this.getRuleContext(0, ExprContext);
	}
	public slist(): SlistContext {
		return this.getRuleContext(0, SlistContext);
	}
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterWhileStatement) {
			listener.enterWhileStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitWhileStatement) {
			listener.exitWhileStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitWhileStatement) {
			return visitor.visitWhileStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class CallStatementContext extends StatementContext {
	public call(): CallContext {
		return this.getRuleContext(0, CallContext);
	}
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterCallStatement) {
			listener.enterCallStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitCallStatement) {
			listener.exitCallStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitCallStatement) {
			return visitor.visitCallStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class EmptyStatementContext extends StatementContext {
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(ctx: StatementContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterEmptyStatement) {
			listener.enterEmptyStatement(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitEmptyStatement) {
			listener.exitEmptyStatement(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitEmptyStatement) {
			return visitor.visitEmptyStatement(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class SlistContext extends ParserRuleContext {
	public NL(): TerminalNode[];
	public NL(i: number): TerminalNode;
	public NL(i?: number): TerminalNode | TerminalNode[] {
		if (i === undefined) {
			return this.getTokens(PieParser.NL);
		} else {
			return this.getToken(PieParser.NL, i);
		}
	}
	public statement(): StatementContext[];
	public statement(i: number): StatementContext;
	public statement(i?: number): StatementContext | StatementContext[] {
		if (i === undefined) {
			return this.getRuleContexts(StatementContext);
		} else {
			return this.getRuleContext(i, StatementContext);
		}
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_slist; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterSlist) {
			listener.enterSlist(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitSlist) {
			listener.exitSlist(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitSlist) {
			return visitor.visitSlist(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class StructDefinitionContext extends ParserRuleContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	public vardef(): VardefContext[];
	public vardef(i: number): VardefContext;
	public vardef(i?: number): VardefContext | VardefContext[] {
		if (i === undefined) {
			return this.getRuleContexts(VardefContext);
		} else {
			return this.getRuleContext(i, VardefContext);
		}
	}
	public NL(): TerminalNode { return this.getToken(PieParser.NL, 0); }
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_structDefinition; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterStructDefinition) {
			listener.enterStructDefinition(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitStructDefinition) {
			listener.exitStructDefinition(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitStructDefinition) {
			return visitor.visitStructDefinition(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class VardefContext extends ParserRuleContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_vardef; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterVardef) {
			listener.enterVardef(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitVardef) {
			listener.exitVardef(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitVardef) {
			return visitor.visitVardef(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class InstanceContext extends ParserRuleContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_instance; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterInstance) {
			listener.enterInstance(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitInstance) {
			listener.exitInstance(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitInstance) {
			return visitor.visitInstance(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class QidContext extends ParserRuleContext {
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_qid; }
	public copyFrom(ctx: QidContext): void {
		super.copyFrom(ctx);
	}
}
export class SimpleVarContext extends QidContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	constructor(ctx: QidContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterSimpleVar) {
			listener.enterSimpleVar(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitSimpleVar) {
			listener.exitSimpleVar(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitSimpleVar) {
			return visitor.visitSimpleVar(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}
export class FieldVarContext extends QidContext {
	public ID(): TerminalNode[];
	public ID(i: number): TerminalNode;
	public ID(i?: number): TerminalNode | TerminalNode[] {
		if (i === undefined) {
			return this.getTokens(PieParser.ID);
		} else {
			return this.getToken(PieParser.ID, i);
		}
	}
	constructor(ctx: QidContext) {
		super(ctx.parent, ctx.invokingState);
		this.copyFrom(ctx);
	}
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterFieldVar) {
			listener.enterFieldVar(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitFieldVar) {
			listener.exitFieldVar(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitFieldVar) {
			return visitor.visitFieldVar(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class FunctionDefinitionContext extends ParserRuleContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	public slist(): SlistContext {
		return this.getRuleContext(0, SlistContext);
	}
	public vardef(): VardefContext[];
	public vardef(i: number): VardefContext;
	public vardef(i?: number): VardefContext | VardefContext[] {
		if (i === undefined) {
			return this.getRuleContexts(VardefContext);
		} else {
			return this.getRuleContext(i, VardefContext);
		}
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_functionDefinition; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterFunctionDefinition) {
			listener.enterFunctionDefinition(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitFunctionDefinition) {
			listener.exitFunctionDefinition(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitFunctionDefinition) {
			return visitor.visitFunctionDefinition(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


export class CallContext extends ParserRuleContext {
	public ID(): TerminalNode { return this.getToken(PieParser.ID, 0); }
	public expr(): ExprContext[];
	public expr(i: number): ExprContext;
	public expr(i?: number): ExprContext | ExprContext[] {
		if (i === undefined) {
			return this.getRuleContexts(ExprContext);
		} else {
			return this.getRuleContext(i, ExprContext);
		}
	}
	constructor(parent: ParserRuleContext | undefined, invokingState: number) {
		super(parent, invokingState);
	}
	// @Override
	public get ruleIndex(): number { return PieParser.RULE_call; }
	// @Override
	public enterRule(listener: PieListener): void {
		if (listener.enterCall) {
			listener.enterCall(this);
		}
	}
	// @Override
	public exitRule(listener: PieListener): void {
		if (listener.exitCall) {
			listener.exitCall(this);
		}
	}
	// @Override
	public accept<Result>(visitor: PieVisitor<Result>): Result {
		if (visitor.visitCall) {
			return visitor.visitCall(this);
		} else {
			return visitor.visitChildren(this);
		}
	}
}


